package design.structure.代理;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * jdk 动态代理
 */
public class DynamicProxy implements InvocationHandler {
    private BuyCar target;

    public DynamicProxy(BuyCar target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Class<?>[] parameterTypes = method.getParameterTypes();
        String methodName = method.getName();

        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return target.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return target.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return target.equals(args[0]);
        }

        System.out.println("开始" + method.getName());
        //todo springAop 切点 是否在这里
        Object result = method.invoke(target, args);
        System.out.println("结束" + method.getName());
        return result;
    }

    /**
     * 静态方法生成代理类
     *
     * @param target
     */
    public static BuyCar getProxy(BuyCar target) {
        return (BuyCar) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(),//接口
                new DynamicProxy(target));
    }

    public static void main(String[] args) {
        /**
         *  生成代理类，并写入硬盘：配置系统属性sun.misc.ProxyGenerator.saveGeneratedFile为true，
         *  代理类生成时将自动将生成的代理类写入硬盘
         */
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        //实际代理对象
        People people = new People("小明");

        //这里得到的 已经是动态生成的参数了
        BuyCar proxy = DynamicProxy.getProxy(people);

        //实现 jdk InvocationHandler 接口
        proxy.buyCar();



        //缓存全部代理
        /**
         * 大 key 接口类名
         * map 小key 方法 名
         * value
         */
        Map<String, Map<String, BuyCar>> CACHE_PROXY = new LinkedHashMap<>();

        Class<?>[] interfaces = proxy.getClass().getInterfaces();
        for (Class<?> aClass : interfaces) {
            String name = aClass.getName();
            String simpleName = aClass.getSimpleName();

            Map<String, BuyCar> buyCarMap = new HashMap<>();
            CACHE_PROXY.put(simpleName, buyCarMap);

            Method[] methods = aClass.getDeclaredMethods();
            for (Method method : methods) {
                String methodName = method.getName();
                int parameterCount = method.getParameterCount();
                Type[] parameterTypes = method.getGenericParameterTypes();
                if (methodName.equals("toString") || methodName.equals("hashCode") || methodName.equals("equals")) {
                    continue;
                }


                //这里直接放 实际要操作的对象
                buyCarMap.put(methodName, people);
            }



        }


//        CACHE_PROXY.values().iterator().next().values().iterator().next().buyCar();
    }
}
